<?php

class AlgoritmoAlocacao {

    private $tabela; //matriz[hora][id_ambiente] = id_disciplina.'-'.turma
    private $turmas;
    public $seconds = 300;
    private $horaInicial = 0;
    private $numHorasPorDia = 0;
    private $arrayIndexesTurmas = array();

    public function __construct($turmas) {
        $this->turmas = $turmas;
        $arrayHora = MethodUtils::getArrayHora();
        foreach ($arrayHora as $key => $value) {
            $this->horaInicial = $key;
            break;
        }
        $this->numHorasPorDia = count($arrayHora);
        $i = 0;
        foreach ($turmas as $key => $value) {
            $this->arrayIndexesTurmas[$i] = $key;
            $i++;
        }
    }

    public function init() {
        set_time_limit($this->seconds);
        $naoAlocados = 0;
        $retorno = $this->run(0);
        
        return $retorno;
    }

    private function run($id) {
        $idCorrente = $this->getTurma($id);
        if ($idCorrente === false){
            return true;
        }else{
            $turma = $this->turmas[$idCorrente];
            $j = 0; //index do array de ambientes
            $alocou = false; //indica se alocou a turma em um ambiente
            if (is_null($turma->indexes)) {
                $turma->indexes = $this->getIndexesHora($turma);
            }
            while($j < count($turma->ambientes) && !$alocou) {
                $alocado = $this->isAlocated($turma->getId(), $turma->ambientes[$j]->ID_AMBIENTE, $turma->indexes);
                if ($alocado == false) {
                        $turma->ambienteSelecionado = $turma->ambientes[$j];
                        $this->alocar($turma->getId(), $turma->ambientes[$j]->ID_AMBIENTE, $turma->indexes);
                        $alocou = true && $this->run($id+1);
                        if ($alocou == false){
                            $turma->ambienteSelecionado = null;
                            $this->desalocar($turma->getId(), $turma->ambientes[$j]->ID_AMBIENTE, $turma->indexes);
                        }
                }else{
                    $alocou = false;
                }
                $j++;
            }
            return $alocou;
        }
    }
    
    private function getTurma($idCorrente){
        if ($idCorrente < count($this->arrayIndexesTurmas)){
            return $this->arrayIndexesTurmas[$idCorrente];
        }else{
            return false;
        }
    }

    private function alocar($idTurma, $idSala, $arrayIndexes) {
        foreach ($arrayIndexes as $idx) {
            $this->tabela[$idx][$idSala] = $idTurma;
        }
    }
    
    private function desalocar($idTurma, $idSala, $arrayIndexes) {
        foreach ($arrayIndexes as $idx) {
            $this->tabela[$idx][$idSala] = null;
        }
    }

    private function isAlocated($idTurma, $idSala, $arrayIndexes) {
        foreach ($arrayIndexes as $idx) {
            if (is_array($this->tabela)) {
                if (array_key_exists($idx, $this->tabela)) {
                    if (array_key_exists($idSala, $this->tabela[$idx])) {
                        $val = $this->tabela[$idx][$idSala];
                        if ($this->tabela[$idx][$idSala] != null) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    private function getIndexesHora(CargaSemestral $turma) {
        $hrIni = intval($this->horaInicial);
        $hi = intval($turma->horaIni);
        $hf = intval($turma->horaFim);
        $idxIni = 1;
        $ret = array();
        while ($hi - $hrIni > 0) {
            if ($hi - $hrIni >= 100) {
                $idxIni += 2;
                $hrIni += 100;
            } else {
                $idxIni += 1;
                $hrIni += $hi - $hrIni;
            }
        }
        $idxFim = $idxIni;
        while ($hf - $hi > 0) {
            if ($hf - $hi >= 100) {
                $idxFim += 2;
                $hi += 100;
            } else {
                $idxFim += 1;
                $hi += $hf - $hi;
            }
        }
        $arrayIndexesDias = $this->getIndexesDias($turma->diasSemana);
        foreach ($arrayIndexesDias as $dia) {
            for ($index = $idxIni; $index < $idxFim; $index++) {
                $calculo = ($this->numHorasPorDia * $dia) + $index;
                $ret = array_merge($ret, array($calculo));
            }
        }
        return $ret;
    }

    private function getIndexesDias($dias) {
        $arrDia = explode('/', $dias);
        $ret = array();
        foreach ($arrDia as $dia) {
            switch ($dia) {
                case 'Dom':
                    $ret = array_merge($ret, array(0));
                    break;
                case 'Seg':
                    $ret = array_merge($ret, array(1));
                    break;
                case 'Ter':
                    $ret = array_merge($ret, array(2));
                    break;
                case 'Qua':
                    $ret = array_merge($ret, array(3));
                    break;
                case 'Qui':
                    $ret = array_merge($ret, array(4));
                    break;
                case 'Sex':
                    $ret = array_merge($ret, array(5));
                    break;
                case 'Sab':
                    $ret = array_merge($ret, array(6));
                    break;
            }
        }
        return $ret;
    }

}

?>
